package com.ruicar.afs.cloud.apply.admin.manage.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.apply.admin.manage.entity.SysPermission;
import com.ruicar.afs.cloud.apply.admin.manage.entity.SysRolePermission;
import com.ruicar.afs.cloud.apply.admin.manage.service.ApplyPermissionService;
import com.ruicar.afs.cloud.apply.admin.manage.service.ApplyRolePermissionService;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.log.annotation.SysLog;
import com.ruicar.afs.cloud.common.core.security.service.AfsUser;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.User;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author: Lee
 * @date: 2020/06/05
 * @description:
 */
@Slf4j
@RestController
@Api(description = "菜单/权限管理接口")
@RequestMapping("/applyPermission")
@AllArgsConstructor
public class ApplyPermissionController {

    private final ApplyPermissionService sysPermissionService;

    private final ApplyRolePermissionService sysRolePermissionService;


    @RequestMapping(value = "/getMenuList", method = RequestMethod.GET)
    @ApiOperation(value = "获取用户页面菜单数据")
    public IResponse<List<SysPermission>> getAllMenuList() {

        List<SysPermission> allUserPermission = null;
        User u = SecurityUtils.getUser();
        //获取用户所有菜单权限
        allUserPermission = sysPermissionService.findByUserId(((AfsUser) u).getId());

        if (allUserPermission == null || allUserPermission.size() == 0) {
            return IResponse.fail("用户没有配置任何菜单请联系管理员");
        }

        //all button
        List<SysPermission> buttonOrAreaList = allUserPermission
                .stream()
                .filter(sysPermission -> CommonConstants.PERMISSION_OPERATION.equals(sysPermission.getType()) || CommonConstants.PERMISSION_AREA.equals(sysPermission.getType()))
                .collect(Collectors.toList());
        //all menu

        List<SysPermission> menuList = new ArrayList<>();

        allUserPermission.forEach(sysPermission -> {
            if (CommonConstants.PERMISSION_PAGE.equals(sysPermission.getType())) {
                menuList.add(sysPermission);
            }
        });

        int level = 1;
        List<SysPermission> permissions = menuList
                .stream()
                .filter(sysPermission -> CommonConstants.PARENT_ID.equals(sysPermission.getParentId()))
                .collect(Collectors.toList());

        permissions.forEach(sysPermission -> {
            findSubPermissionAndButton(sysPermission, menuList, buttonOrAreaList, level, false);
        });

        return new IResponse<List<SysPermission>>().setData(permissions);
    }

    @RequestMapping(value = "/getAllList", method = RequestMethod.GET)
    @ApiOperation(value = "获取权限菜单树")
    @PreAuthorize("@pms.hasPermission('sys_permission_query')")
    public IResponse<List<SysPermission>> getAllList() {

        //all permission
        List<SysPermission> allUserPermission = sysPermissionService.list();

        //all button
        List<SysPermission> buttonOrAreaList = allUserPermission
                .stream()
                .filter(sysPermission -> CommonConstants.PERMISSION_OPERATION.equals(sysPermission.getType()) || CommonConstants.PERMISSION_AREA.equals(sysPermission.getType()))
                .collect(Collectors.toList());
        //all menu

        List<SysPermission> menuList = new ArrayList<>();
        allUserPermission.forEach(sysPermission -> {
            if (CommonConstants.PERMISSION_PAGE.equals(sysPermission.getType())) {
                menuList.add(sysPermission);
            }
        });
        int level = 1;
        List<SysPermission> permissions = menuList
                .stream()
                .filter(sysPermission -> CommonConstants.PARENT_ID.equals(sysPermission.getParentId()))
                .collect(Collectors.toList());

        permissions.forEach(sysPermission -> {
            findSubPermissionAndButton(sysPermission, menuList, buttonOrAreaList, level, true);
        });

        return new IResponse<List<SysPermission>>().setData(permissions);
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ApiOperation(value = "添加")
    @Transactional
    @SysLog("添加菜单")
    @PreAuthorize("@pms.hasPermission('sys_permission_add')")
    @CacheEvict(value = CommonConstants.USER_CACHE_KEY_PREFIX, allEntries = true)
    public IResponse<SysPermission> add(@RequestBody SysPermission permission) {

        // 判断拦截请求的操作权限按钮名是否已存在
        if (CommonConstants.PERMISSION_OPERATION.equals(permission.getType())) {
            List<SysPermission> list = sysPermissionService.findByTitle(permission.getTitle());
            if (list != null && list.size() > 0) {
                return new IResponse<SysPermission>().setMsg("名称已存在");
            }
        }
        if (permission.getParentId() == null) {
            permission.setParentId(0l);
        }
        sysPermissionService.save(permission);
        //手动删除缓存
        return new IResponse<SysPermission>().setData(permission);
    }

    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @ApiOperation(value = "编辑")
    @Transactional
    @SysLog("编辑菜单")
    @PreAuthorize("@pms.hasPermission('sys_permission_edit')")
    @CacheEvict(value = "user_details", allEntries = true)
    public IResponse<SysPermission> edit(@RequestBody SysPermission permission) {

        // 判断拦截请求的操作权限按钮名是否已存在
        if (CommonConstants.PERMISSION_OPERATION.equals(permission.getType())) {
            // 若名称修改
            SysPermission p = sysPermissionService.getById(permission.getId());
            if (!p.getTitle().equals(permission.getTitle())) {
                List<SysPermission> list = sysPermissionService.findByTitle(permission.getTitle());
                if (list != null && list.size() > 0) {
                    return new IResponse<SysPermission>().setMsg("名称已存在");
                }
            }
        }
        sysPermissionService.updateById(permission);
        return new IResponse<SysPermission>().setData(permission);
    }

    @RequestMapping(value = "/delByIds/{ids}", method = RequestMethod.DELETE)
    @ApiOperation(value = "批量通过id删除")
    @Transactional
    @SysLog("删除菜单")
    @PreAuthorize("@pms.hasPermission('sys_permission_delete')")
    @CacheEvict(value = "user_details", allEntries = true)
    public IResponse<Object> delByIds(@PathVariable Long[] ids) {

        for (Long id : ids) {
            List<SysRolePermission> list = sysRolePermissionService.list(Wrappers
                    .<SysRolePermission>query().lambda()
                    .eq(SysRolePermission::getRoleId, id));
            if (list != null && list.size() > 0) {
                return new IResponse().setMsg("删除失败，包含正被角色使用关联的菜单或权限");
            }
        }
        sysPermissionService.removeByIds(Arrays.asList(ids));
        return new IResponse().setMsg("批量通过id删除数据成功");
    }

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    @ApiOperation(value = "搜索菜单")
    @PreAuthorize("@pms.hasPermission('sys_permission_query')")
    public IResponse<List<SysPermission>> searchPermissionList(@RequestParam String title) {

        List<SysPermission> list = sysPermissionService.findByTitleLikeOrderBySortOrder(title);
        return new IResponse<List<SysPermission>>().setData(list);
    }

    private void findSubPermissionAndButton(SysPermission permission, List<SysPermission> allPermission, List<SysPermission> buttons, int level, boolean buttonAsChild) {


        List<SysPermission> children = allPermission
                .stream()
                .filter(child -> permission.getId().equals(child.getParentId()))
                .collect(Collectors.toList());

        List<SysPermission> childrenButtons = buttons
                .stream()
                .filter(button -> permission.getId().equals(button.getParentId()))
                .collect(Collectors.toList());

        permission.setPermTypes(
                childrenButtons.stream()
                        .filter(button -> StringUtils.isNotEmpty(button.getPermissions()))
                        .map(button -> button.getPermissions().split(","))
                        .flatMap(permissions -> Arrays.stream(permissions))
                        .collect(Collectors.toList())
        );

        if (children.size() == 0) {
            if (buttonAsChild) {
                children.addAll(childrenButtons);
                permission.setChildren(children);
            }
            return;
        }

        if (buttonAsChild) {
            children.addAll(childrenButtons);
            permission.setChildren(children);
        }
        children.forEach(child -> {
            child.setLevel(level + 1);
            findSubPermissionAndButton(child, allPermission, buttons, level + 1, buttonAsChild);
        });


        permission.setChildren(children);
    }
}
